package ru.compscicenter.databases.zaikina.common.commands;

import org.json.simple.JSONArray;
import org.json.simple.JSONAware;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import ru.compscicenter.databases.zaikina.common.commands.bodies.CommandBody;
import ru.compscicenter.databases.zaikina.common.model.WordWithReferences;

import java.util.ArrayList;

public class SysCommand<T, E extends CommandBody<T>> implements JSONAware {
    private final Integer type;
    private final Integer param;
    private final T body;

    SysCommand(Integer type, E body, Integer param) {
        if (body != null) {
            this.body = body.getValue();
        } else {
            this.body = null;
        }
        this.type = type;
        this.param = param;
    }

    SysCommand(Integer type, T body, Integer param) {
        this.type = type;
        this.body = body;
        this.param = param;
    }

    public Integer getType() {
        return type;
    }

    public T getBody() {
        return body;
    }

    public Integer getParam() {
        return param;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof SysCommand) {
            SysCommand sysCommand = (SysCommand) obj;
            return sysCommand.type.equals(type) && body.equals(sysCommand.body) && param.equals(sysCommand.param);
        }
        return super.equals(obj);
    }

    public static int parseType(String jsonStr) {
        return parseType((JSONObject) JSONValue.parse(jsonStr));
    }

    static int parseType(JSONObject obj) {
        try {
            return Integer.parseInt(obj.get("type").toString());
        } catch (NumberFormatException ex) {
            return -1;
        }
    }

    static <T, E extends CommandBody<T>> SysCommand parse(JSONObject obj, E body) {
        Integer type;
        Integer param;
        try {
            type = Integer.parseInt(obj.get("type").toString());
            param = Integer.parseInt(obj.get("param").toString());
            body.getFromJsonString(obj.get("body").toString());
        } catch (Exception ex) {
            return null;
        }
        return new SysCommand(type, body, param);
    }

    public static SysCommand<?, ?> parse(String jsonStr) {
        EmptyCommand emptyCommand = EmptyCommand.parse(jsonStr);
        if (emptyCommand != null) {
            return emptyCommand;
        }

        DocumentsCommand documentsCommand = DocumentsCommand.parse(jsonStr);
        if (documentsCommand != null) {
            return documentsCommand;
        }

        FullDocumentsCommand fullDocumentsCommand = FullDocumentsCommand.parse(jsonStr);
        if (fullDocumentsCommand != null) {
            return fullDocumentsCommand;
        }

        FullWordsCommand fullWordsCommand = FullWordsCommand.parse(jsonStr);
        if (fullWordsCommand != null) {
            return fullWordsCommand;
        }

        StringListCommand stringListCommand = StringListCommand.parse(jsonStr);
        if (stringListCommand != null) {
            return stringListCommand;
        }

        WordsCommand wordsCommand = WordsCommand.parse(jsonStr);
        if (wordsCommand != null) {
            return wordsCommand;
        }
        return null;
    }

    public String toJSONString() {
        JSONObject obj = new JSONObject();
        obj.put("type", type);
        obj.put("param", param);
        obj.put("body", body);
        return obj.toString();
    }
}
